/**
 * Created : Apr 13, 2012
 *
 * @author pquiring
 */

import java.awt.*;
import javax.swing.table.*;

import javaforce.*;

public class BlueToothDialog extends javax.swing.JFrame {

  /**
   * Creates new form BlueToothDialog
   */
  public BlueToothDialog() {
    super();
    initComponents();
    model = (DefaultTableModel)table.getModel();
    devices.setVisible(false);
    setPosition();
    setAlwaysOnTop(true);
    toFront();
    setStatus("Status : Finding controllers...");
    Dock.jbusClient.call("org.jflinux.jnetworkmgr", "getBTdevices", quote(Dock.jbusClient.pack));
  }

  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  @SuppressWarnings("unchecked")
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    jToolBar1 = new javax.swing.JToolBar();
    scan = new javax.swing.JButton();
    connect = new javax.swing.JButton();
    devices = new javax.swing.JComboBox();
    status = new javax.swing.JLabel();
    jScrollPane2 = new javax.swing.JScrollPane();
    table = new javax.swing.JTable();

    setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
    setTitle("Bluetooth Setup");
    setResizable(false);
    addWindowListener(new java.awt.event.WindowAdapter() {
      public void windowClosing(java.awt.event.WindowEvent evt) {
        formWindowClosing(evt);
      }
    });

    jToolBar1.setFloatable(false);
    jToolBar1.setRollover(true);

    scan.setText("Scan");
    scan.setEnabled(false);
    scan.setFocusable(false);
    scan.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
    scan.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
    scan.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        scanActionPerformed(evt);
      }
    });
    jToolBar1.add(scan);

    connect.setText("Connect");
    connect.setEnabled(false);
    connect.setFocusable(false);
    connect.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
    connect.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
    connect.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        connectActionPerformed(evt);
      }
    });
    jToolBar1.add(connect);

    devices.addItemListener(new java.awt.event.ItemListener() {
      public void itemStateChanged(java.awt.event.ItemEvent evt) {
        devicesItemStateChanged(evt);
      }
    });
    jToolBar1.add(devices);

    status.setText("Status : Ready");

    table.setModel(new javax.swing.table.DefaultTableModel(
      new Object [][] {

      },
      new String [] {
        "Name", "MAC"
      }
    ) {
      Class[] types = new Class [] {
        java.lang.String.class, java.lang.String.class
      };
      boolean[] canEdit = new boolean [] {
        false, false
      };

      public Class getColumnClass(int columnIndex) {
        return types [columnIndex];
      }

      public boolean isCellEditable(int rowIndex, int columnIndex) {
        return canEdit [columnIndex];
      }
    });
    jScrollPane2.setViewportView(table);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 396, Short.MAX_VALUE)
      .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
          .addComponent(status, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        .addContainerGap())
    );
    layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
        .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(status)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 265, Short.MAX_VALUE)
        .addContainerGap())
    );

    pack();
  }// </editor-fold>//GEN-END:initComponents

  private void scanActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_scanActionPerformed
    scan();
  }//GEN-LAST:event_scanActionPerformed

  private void connectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectActionPerformed
    connect();
  }//GEN-LAST:event_connectActionPerformed

  private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
    Dock.btDialog = null;
  }//GEN-LAST:event_formWindowClosing

  private void devicesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_devicesItemStateChanged
    clear();
  }//GEN-LAST:event_devicesItemStateChanged

  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JButton connect;
  private javax.swing.JComboBox devices;
  private javax.swing.JScrollPane jScrollPane2;
  private javax.swing.JToolBar jToolBar1;
  private javax.swing.JButton scan;
  private javax.swing.JLabel status;
  private javax.swing.JTable table;
  // End of variables declaration//GEN-END:variables

  private DefaultTableModel model;
  private boolean enabling, scanning, connecting;
  private String deviceList[];
  private int deviceIdx = -1;

  private void setPosition() {
    Rectangle s = JFAWT.getMaximumBounds();
    Dimension d = getPreferredSize();
    setSize(d.width, d.height);
    setLocation(s.width/2 - d.width/2, s.height/2 - (d.height/2));
  }

  private void scan() {
    if (enabling || scanning || connecting) return;
    deviceIdx = devices.getSelectedIndex();
    devices.setEnabled(false);
    scanning = true;
    if (!isBTEnabled()) {
      enabling = true;
      Dock.jbusClient.call("org.jflinux.jnetworkmgr", "enableBTdevice",
        quote(Dock.jbusClient.pack) + "," + quote(deviceList[deviceIdx*2]));
      setStatus("Status : Enabling controller...");
      return;
    }
    setStatus("Scanning...");
    clear();
    new Thread() {
      public void run() {
        ShellProcess sp = new ShellProcess();
        final String output = sp.run(new String[] {"hcitool", "scan"}, false);
        EventQueue.invokeLater(new Runnable() {
          public void run() {
            String lns[] = output.split("\n");
            for(int a=1;a<lns.length;a++) {
              if (!lns[a].startsWith("\t")) continue;
              String f[] = lns[a].substring(1).split("\t");
              //0=mac 1=desc
              model.addRow(new Object[] {f[1], f[0]});
            }
            setStatus("Status : Ready");
            scanning = false;
            if (model.getRowCount() > 0) {
              connect.setEnabled(true);
            }
          }
        });
      }
    }.start();
  }

  String desc, mac;

  private String quote(String str) {
    return '\"' + str + '\"';
  }

  private void connect() {
    if (enabling || scanning || connecting) return;
    deviceIdx = devices.getSelectedIndex();
    if (!isBTEnabled()) return;
    devices.setEnabled(false);
    int row = table.getSelectedRow();
    if (row == -1) return;
    connecting = true;
    mac = (String)table.getValueAt(row, 1);
    desc = (String)table.getValueAt(row, 0);
    Dock.jbusClient.call("org.jflinux.jnetworkmgr", "connectBT",
      quote(Dock.jbusClient.pack) + "," + quote(deviceList[deviceIdx*2]) + "," + quote(mac));
    setStatus("Connecting to " + desc);
  }

  public void success() {
    if (connecting) {
      setStatus("Connection successful");
      Dock.BlueToothDevice dev = new Dock.BlueToothDevice();
      dev.desc = desc;
      dev.mac = mac;
      Dock.btDevices.add(dev);
      connecting = false;
    } else if (enabling) {
      setStatus("Status : Ready");
      deviceList[deviceIdx*2+1] = "UP";
      enabling = false;
      devices.setEnabled(true);
      if (scanning) {
        scanning = false;
        scan();
      }
    }
  }

  public void failed() {
    if (connecting) {
      setStatus("Connection failed");
      connecting = false;
    } else if (enabling) {
      setStatus("Status : Controller failed to start");
      enabling = false;
      if (scanning) scanning = false;
    }
  }

  public void setStatus(String msg) {
    status.setText(msg);
  }

  private boolean isBTEnabled() {
    return (deviceList[deviceIdx * 2 + 1].equals("UP"));
  }

  public void devices(String list) {
    if (list.length() == 0) {
      //this should NOT happen
      JFAWT.showError("Error", "No BlueTooth controllers found");
      dispose();
      return;
    }
    //list = dev | UP or DOWN | ...
    deviceList = list.split("[|]");
    devices.removeAllItems();
    if (deviceList.length > 2) {
      for(int a=0;a<deviceList.length;a += 2) {
        devices.addItem(deviceList[a]);
      }
      deviceIdx = 0;
      setStatus("Status : Ready");
    } else {
      devices.addItem(deviceList[0]);
      devices.setVisible(false);
      deviceIdx = 0;
      if (!isBTEnabled()) {
        enabling = true;
        setStatus("Enabling controller");
        Dock.jbusClient.call("org.jflinux.jnetworkmgr", "enableBTdevice",
          quote(Dock.jbusClient.pack) + "," + quote(deviceList[0]));
      } else {
        setStatus("Status : Ready");
      }
    }
    scan.setEnabled(true);
  }

  private void clear() {
    while (model.getRowCount() > 0) model.removeRow(0);
  }
}
